package cn.iocoder.yudao.module.digital.service.cardchannel.impl.bh;

import cn.hutool.core.util.IdUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.digital.enums.cardkeysecret.CardKeyApiRequestTypeEnum;
import cn.iocoder.yudao.module.digital.framework.cardkey.config.CardKeyConfig;
import cn.iocoder.yudao.module.digital.service.cardchannel.constant.CardKeyThirdPartyApiConstant;
import cn.iocoder.yudao.module.digital.service.cardchannel.model.*;
import cn.iocoder.yudao.module.digital.service.cardchannel.impl.bh.util.CardKeyThirdPartyApiHttpUtil;
import cn.iocoder.yudao.module.digital.service.cardchannel.impl.bh.util.CardKeyThirdPartyApiUtil;
import cn.iocoder.yudao.module.digital.service.cardkeythirdpartyapirecord.CardkeyThirdPartyApiRecordService;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Map;

/**
 * Description: 卡密管理实现
 * Author: li
 * Date: 2024/2/21
 */
@Component
@Slf4j
public class CardKeyThirdPartyBHApiImpl implements ICardKeyThirdPartyBHApi {
    @Resource
    private CardKeyConfig cardKeyConfig;
    @Resource
    private CardkeyThirdPartyApiRecordService apiRecordService;

    @PostConstruct
    public void initHttpClient() throws Exception {
        CardKeyThirdPartyApiHttpUtil.initHttpClient(cardKeyConfig);
    }


    @Override
    public GenerateEGiftResponseWrapper generateCard(GenerateEGiftRequestWrapper requestWrapper) {
        GenerateEGiftResponseWrapper responseWrapper = null;
        String generateEGiftRequestId = null;
        for (int i = 0; i < 3; i++) {
            if (StringUtil.isEmpty(generateEGiftRequestId)) {
                generateEGiftRequestId = IdUtil.fastSimpleUUID();
            }
            responseWrapper = generateCard(i, generateEGiftRequestId, requestWrapper);
            generateEGiftRequestId = responseWrapper.getNextIndexGenerateEGiftRequestId();

            if (responseWrapper.isGenerateEGiftSuccess()) {
                break;
            }

            final Integer generateEGiftStatusCode = responseWrapper.getGenerateEGiftStatusCode();
            if (!CardKeyThirdPartyApiConstant.HTTP_STATUS_CODE_REVERSE.contains(generateEGiftStatusCode)) {
                break;
            }

            if (responseWrapper.isRevertSuccess()) {
                break;
            }
        }
        return responseWrapper;
    }

    /**
     * 生成礼品卡
     *
     * @param requestWrapper
     * @return
     */
    private GenerateEGiftResponseWrapper generateCard(int index, String generateEGiftRequestId, GenerateEGiftRequestWrapper requestWrapper) {
        // 创建api请求记录
        final String generateCardUri = cardKeyConfig.getHost() + cardKeyConfig.getGenerateCardUri();

        // headers
        final String mid = cardKeyConfig.getMid();
        final String tenantId = cardKeyConfig.getTenantId();
        final Map<String, String> headers = CardKeyThirdPartyApiHttpUtil.createHeaders(generateEGiftRequestId, mid, tenantId, requestWrapper.getOrderNo());

        final Long apiRecordId = apiRecordService.createApiRecord(
                CardKeyApiRequestTypeEnum.GENERATE, requestWrapper.getOrderNo(), requestWrapper.getProductNo(),
                requestWrapper.getCurrencyCode(), requestWrapper.getDenomination(),
                generateEGiftRequestId, generateCardUri, null, headers, generateEGiftRequestId);

        // 生成交易的检索参考号
        final String retrievalReferenceNumber = CardKeyThirdPartyApiUtil.generateRetrievalReferenceNumber(apiRecordId);
        requestWrapper.getRequest().setRetrievalReferenceNumber(retrievalReferenceNumber);

        // 存储请求body
        final String requestBody = JsonUtils.toJsonString(requestWrapper.getRequest());
        apiRecordService.updateApiRecordWithRequestBody(apiRecordId, requestBody);

        // 调用api生成Card
        final GenerateEGiftResponseWrapper responseWrapper = callGenerateCardAPI(generateEGiftRequestId, index, requestBody, headers, apiRecordId);

        if (responseWrapper.isGenerateEGiftSuccess()) {
            // 查询卡密
            final GetAccountResponseWrapper getAccountResponseWrapper = callGetAccountAPIWithRetry(requestWrapper, responseWrapper, generateEGiftRequestId);
            responseWrapper.setGetAccountResponseWrapper(getAccountResponseWrapper);
        } else {
            if (responseWrapper.isNeedRevert()) {
                // 撤销卡密
                final ReverseEGiftResponse reverseResponse = callReverseCardAPI(index, generateEGiftRequestId, requestWrapper);
                if (!reverseResponse.isSuccess()) {
                    // 撤销失败，再次调用生成卡接口时generateEGiftRequestId保持不变
                    responseWrapper.setNextIndexGenerateEGiftRequestId(generateEGiftRequestId);
                } else {
                    responseWrapper.setRevertSuccess(true);
                }
            }
        }

        return responseWrapper;
    }

//    // 撤销卡密
//    private void callReverseCardAPIWithRetry(GenerateEGiftRequestWrapper requestWrapper, String requestId) {
//        ReverseEGiftResponse reverseEGiftResponse = null;
//        for (int i = 0; i < 3; i++) {
//            reverseEGiftResponse = callReverseCardAPI(i, requestId, requestWrapper);
//            if (reverseEGiftResponse.isSuccess()) {
//                break;
//            }
//        }
//    }

    // 查询卡密
    private GetAccountResponseWrapper callGetAccountAPIWithRetry(GenerateEGiftRequestWrapper requestWrapper, GenerateEGiftResponseWrapper responseWrapper,
                                                                 String generateEGiftRequestId) {
        GetAccountResponseWrapper getAccountResponseWrapper = null;
        for (int i = 0; i < 3; i++) {
            final String accountId = responseWrapper.getGenerateEGiftResponse().getAccountId();
            getAccountResponseWrapper = callGetAccountAPI(i, accountId, requestWrapper, generateEGiftRequestId);
            if (getAccountResponseWrapper.isSuccess()) {
                break;
            }
        }
        return getAccountResponseWrapper;
    }

//    // 生成卡密
//    private GenerateEGiftResponseWrapper callGenerateCardAPIWithRetry(String requestId, String requestBody,
//                                                                      Map<String, String> headers,
//                                                                      Long apiRecordId) {
//        GenerateEGiftResponseWrapper responseWrapper = null;
//        for (int i = 0; i < 3; i++) {
//            responseWrapper = callGenerateCardAPI(requestId, i, requestBody, headers, apiRecordId);
//            if (responseWrapper.isGenerateEGiftSuccess()) {
//                break;
//            }
//        }
//        return responseWrapper;
//    }

    // 调用api生成卡密
    private GenerateEGiftResponseWrapper callGenerateCardAPI(String generateEGiftRequestId, int index, String requestBody, Map<String, String> headers,
                                                             Long apiRecordId) {
        final String generateCardUri = cardKeyConfig.getHost() + cardKeyConfig.getGenerateCardUri();
        final EGiftHttpResponse httpResponse = CardKeyThirdPartyApiHttpUtil.sendRequest(index, ThirdPartyApiRequestTypeEnum.POST, generateCardUri,
                requestBody, headers);

        final int statusCode = httpResponse.getStatusCode();
        if (statusCode == CardKeyThirdPartyApiConstant.HTTP_STATUS_CODE_SUCCESS) {
            final String responseContent = httpResponse.getResponseContent();
            final GenerateEGiftResponse response = JsonUtils.parseObject(responseContent, GenerateEGiftResponse.class);

            // 更新api请求记录-成功
            apiRecordService.updateApiRecordWithSuccessResponse(apiRecordId, responseContent);

            return new GenerateEGiftResponseWrapper(generateEGiftRequestId, response, statusCode, true, null, false);
        } else {
            // 更新api请求记录-失败
            apiRecordService.updateApiRecordWithErrorResponse(apiRecordId, statusCode, httpResponse.getResponseContent(), httpResponse.getErrorResponse());

            // 是否需要重试
            final boolean needRevert = CardKeyThirdPartyApiConstant.HTTP_STATUS_CODE_REVERSE.contains(statusCode);
            final String errorMsg = getErrorMsg("生成卡密", statusCode, httpResponse.getErrorResponse());
            return new GenerateEGiftResponseWrapper(generateEGiftRequestId, null, statusCode, false, errorMsg, needRevert);
        }
    }

    // 查询卡密账户
    private GetAccountResponseWrapper callGetAccountAPI(int index, String accountIdUrl, GenerateEGiftRequestWrapper requestWrapper,
                                                        String generateEGiftRequestId) {
        final String mid = cardKeyConfig.getMid();
        final String tenantId = cardKeyConfig.getTenantId();
        final String requestId = IdUtil.fastSimpleUUID();

        final Map<String, String> headers = CardKeyThirdPartyApiHttpUtil.createHeaders(requestId, mid, tenantId, index, requestWrapper.getOrderNo());

        // 创建api请求记录
//        final Long apiRecordId = apiRecordService.createApiRecord(
//                CardKeyApiRequestTypeEnum.GET_ACCOUNT, requestWrapper.getOrderNo(), requestWrapper.getProductNo(),
//                requestWrapper.getCurrencyCode(), requestWrapper.getDenomination(),
//                requestId, accountIdUrl, null, headers, generateEGiftRequestId);
        final Long apiRecordId = null;
        return callGetAccountAPI(index, apiRecordId, accountIdUrl, headers);
    }

    @Override
    public GetAccountResponseWrapper queryOrder(String cardOrderId, String accountId) {
        final int index = 0;
        final String mid = cardKeyConfig.getMid();
        final String tenantId = cardKeyConfig.getTenantId();
        final String requestId = IdUtil.fastSimpleUUID();

        final Map<String, String> headers = CardKeyThirdPartyApiHttpUtil.createHeaders(requestId, mid, tenantId, index, cardOrderId);

        final String accountIdUrl = cardKeyConfig.getHost() + cardKeyConfig.getGetAccountUri() + accountId;
        return callGetAccountAPI(index, null, accountIdUrl, headers);
    }

    // 查询卡密账户
    @Override
    public GetAccountResponseWrapper callGetAccountAPI(int index, Long apiRecordId, String url, Map<String, String> headers) {
        final EGiftHttpResponse httpResponse = CardKeyThirdPartyApiHttpUtil.sendRequest(index, ThirdPartyApiRequestTypeEnum.GET, url, null, headers);
        final int statusCode = httpResponse.getStatusCode();

        if (statusCode == CardKeyThirdPartyApiConstant.HTTP_STATUS_CODE_SUCCESS) {
            final String responseContent = httpResponse.getResponseContent();
            final GetAccountResponse response = JsonUtils.parseObject(responseContent, GetAccountResponse.class);

            // 更新api请求记录-成功，放到调用方必须得跟保存卡密密钥在一个事务中
            return new GetAccountResponseWrapper(apiRecordId, responseContent, response, true, null);
        } else {
            // 更新api请求记录-失败
            if (apiRecordId != null) {
                apiRecordService.updateApiRecordWithErrorResponse(apiRecordId, statusCode, httpResponse.getResponseContent(), httpResponse.getErrorResponse());
            }
            final String errorMsg = getErrorMsg("查询卡密账户", statusCode, httpResponse.getErrorResponse());
            return new GetAccountResponseWrapper(apiRecordId, null, null, false, errorMsg);
        }
    }

    // 撤销卡密
    @Override
    public ReverseEGiftResponse callReverseCardAPI(int index, String generateEGiftRequestId, GenerateEGiftRequestWrapper requestWrapper) {
        final ReverseEGiftRequest requestDTO = new ReverseEGiftRequest();
        requestDTO.setReversalEGiftRequestId(generateEGiftRequestId);

        final String url = cardKeyConfig.getHost() + cardKeyConfig.getReverseCardUri();
        final String requestBody = JsonUtils.toJsonString(requestDTO);

        final String mid = cardKeyConfig.getMid();
        final String tenantId = cardKeyConfig.getTenantId();
        final String requestId = IdUtil.fastSimpleUUID();
        final Map<String, String> headers = CardKeyThirdPartyApiHttpUtil.createHeaders(requestId, mid, tenantId, requestWrapper.getOrderNo());

        // 创建api请求记录
        final Long apiRecordId = apiRecordService.createApiRecord(
                CardKeyApiRequestTypeEnum.REVERSE, requestWrapper.getOrderNo(), requestWrapper.getProductNo(),
                requestWrapper.getCurrencyCode(), requestWrapper.getDenomination(),
                requestId, url, requestBody, headers, generateEGiftRequestId);

        // 发送撤销请求
        return sendReverseCardRequest(index, url, requestBody, headers, apiRecordId);
    }

    // 发送撤销请求
    private ReverseEGiftResponse sendReverseCardRequest(int index, String url, String requestBody, Map<String, String> headers, Long apiRecordId) {
        final EGiftHttpResponse httpResponse = CardKeyThirdPartyApiHttpUtil.sendRequest(index, ThirdPartyApiRequestTypeEnum.POST, url, requestBody, headers);
        final int statusCode = httpResponse.getStatusCode();

        boolean success = false;
        String transactionStatus = null;
        final String responseContent = httpResponse.getResponseContent();
        if (statusCode == CardKeyThirdPartyApiConstant.HTTP_STATUS_CODE_SUCCESS) {
            final ReverseEGiftRes reverseEGiftRes = JsonUtils.parseObject(responseContent, ReverseEGiftRes.class);
            if (reverseEGiftRes.getIsReversal() != null && reverseEGiftRes.getIsReversal() && "APPROVED".equals(reverseEGiftRes.getTransactionStatus())) {
                success = true;
                log.info("调用黑鹰API-撤销成功, index = {}, statusCode = {}, isReversal = {}, transactionStatus = {}",
                        index, statusCode, reverseEGiftRes.getIsReversal(), reverseEGiftRes.getTransactionStatus());
            } else {
                transactionStatus = reverseEGiftRes.getTransactionStatus();
                log.warn("调用黑鹰API-撤销失败, index = {}, statusCode = {}, isReversal = {}, transactionStatus = {}",
                        index, statusCode, reverseEGiftRes.getIsReversal(), reverseEGiftRes.getTransactionStatus());
            }
        }

        if (success) {
            // 更新api请求记录-成功
            apiRecordService.updateApiRecordWithSuccessResponse(apiRecordId, responseContent);
            final ReverseEGiftResponse response = new ReverseEGiftResponse(responseContent, true, null);
            return response;
        } else {
            // 更新api请求记录-失败
            apiRecordService.updateApiRecordWithErrorResponse(apiRecordId, statusCode, httpResponse.getResponseContent(), httpResponse.getErrorResponse());
            final String errorMsg = getErrorMsg("撤销卡密", statusCode, transactionStatus, httpResponse.getErrorResponse());
            return new ReverseEGiftResponse(null, false, errorMsg);
        }
    }

    private String getErrorMsg(String action, int statusCode, String transactionStatus, EGiftErrorResponse errorResponse) {
        final String errorMsg;
        if (errorResponse != null) {
            final String errorCode = errorResponse.getErrorCode();
            final String message = errorResponse.getMessage();
            errorMsg = String.format("请求黑鹰API失败, action = %s, statusCode = %s, errorCode = %s, message = %s, transactionStatus = %s",
                    action, statusCode, errorCode, message, transactionStatus);
        } else {
            errorMsg = String.format("请求黑鹰API失败, action = %s, statusCode = %s, transactionStatus = %s",
                    action, statusCode, transactionStatus);
        }
        return errorMsg;
    }

    /*********************product***********************/

    // 获取产品目录列表
    @Override
    public ProductCatalogsResponse getGetProductCatalogs() {
        final String url = cardKeyConfig.getHost() + cardKeyConfig.getGetProductCatalogsUri();
        final EGiftHttpResponse httpResponse = CardKeyThirdPartyApiHttpUtil.sendRequest(0, ThirdPartyApiRequestTypeEnum.GET,
                url, null, null);
        final int statusCode = httpResponse.getStatusCode();
        if (statusCode == CardKeyThirdPartyApiConstant.HTTP_STATUS_CODE_SUCCESS) {
            final String responseContent = httpResponse.getResponseContent();
            final ProductCatalogsResponse response = JsonUtils.parseObject(responseContent, ProductCatalogsResponse.class);
            return response;
        } else {
            final String errorMsg = getErrorMsg("获取产品目录列表", statusCode, httpResponse.getErrorResponse());
            throw new RuntimeException(errorMsg);
        }
    }

    // 获取目录下的产品
    @Override
    public ProductCatalogResponse getGetProductCatalog(String entityIdUrl) {
        final String url = entityIdUrl;
        final EGiftHttpResponse httpResponse = CardKeyThirdPartyApiHttpUtil.sendRequest(0, ThirdPartyApiRequestTypeEnum.GET,
                url, null, null);
        final int statusCode = httpResponse.getStatusCode();
        if (statusCode == CardKeyThirdPartyApiConstant.HTTP_STATUS_CODE_SUCCESS) {
            final String responseContent = httpResponse.getResponseContent();
            final ProductCatalogResponse response = JsonUtils.parseObject(responseContent, ProductCatalogResponse.class);
            return response;
        } else {
            final String errorMsg = getErrorMsg("获取目录下的产品", statusCode, httpResponse.getErrorResponse());
            throw new RuntimeException(errorMsg);
        }
    }

    // 获取产品
    @Override
    public ProductResponseWrapper getProduct(String productIdUrl) {
        final String url = productIdUrl;
        final EGiftHttpResponse httpResponse = CardKeyThirdPartyApiHttpUtil.sendRequest(0, ThirdPartyApiRequestTypeEnum.GET,
                url, null, null);
        final int statusCode = httpResponse.getStatusCode();
        if (statusCode == CardKeyThirdPartyApiConstant.HTTP_STATUS_CODE_SUCCESS) {
            final String responseContent = httpResponse.getResponseContent();
            final ProductResponse response = JsonUtils.parseObject(responseContent, ProductResponse.class);
            return new ProductResponseWrapper(response, responseContent);
        } else {
            final String errorMsg = getErrorMsg("获取产品", statusCode, httpResponse.getErrorResponse());
            throw new RuntimeException(errorMsg);
        }
    }

    private String getErrorMsg(String action, int statusCode, EGiftErrorResponse errorResponse) {
        final String errorMsg;
        if (errorResponse != null) {
            final String errorCode = errorResponse.getErrorCode();
            final String message = errorResponse.getMessage();
            errorMsg = String.format("请求黑鹰API失败, action = %s, statusCode = %s, errorCode = %s, message = %s", action, statusCode, errorCode, message);
        } else {
            errorMsg = String.format("请求黑鹰API失败, action = %s, statusCode = %s", action, statusCode);
        }
        return errorMsg;
    }

}
